package main.java.com.silence.utils;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Properties;

/**
 * 邮件工具
 *
 * 用 javax.mail 实现的，未使用Spring Mail
 *
 * Created by Silence on 2017/5/17.
 */
public class MailUtils {

    private static MimeMessage mimeMsg;     //MIME类型的消息
    private static Session session;     //邮件会话
    private static Properties props;    //是 java.util.Properties 类型对象
    private static String username = "";    //用于SMTP认证的用户名和密码
    private static String password = "";
    private static Multipart mp;    //MIME消息的内容
    private static boolean ifMimeBody = true;  // 邮件内容是否为MIME类型的

    /**
     * 发送验证码
     * @param to 接收者
     * @param code 验证码
     * @return 发送成功与否
     */
    public static boolean sendMail(String to, String code) {

        String subject = "来自Silence的激活邮件";
        String body = "<h1>来自Silence网站的激活邮件，激活请点击一下链接：</h1>" +
        "<a href='http://localhost:8080/activate/" + code +"'>http://localhost:8080/activate/" + code +"</a>";

        return sendMail(subject, body, to, null);
    }

    /**
     * 发送邮件
     * @param smtp -> String  SMTP服务器
     * @param subject -> String 邮件主题
     * @param body -> String    邮件内容
     * @param ifMimeBody -> boolean 邮件内容是否为MIME类型的
     * @param from -> String  发送人
     * @param to -> String    接收者
     * @param coypto -> String    抄送人
     * @param bcto -> String          暗抄送人
     * @param senderUserName -> String  发送者用户名 (用于在服务器上验证身份)
     * @param senderPass -> String    发送者密码
     * @param fileAffix     附件
     * @return 发送成功与否
     */
    private static boolean sendMail(String smtp, String subject, String body, boolean ifMimeBody,
                                    String from, String to, String coypto,
                                    String bcto, String senderUserName, String senderPass, String fileAffix) {
        setNeedAuth(true);

        setSmtpHost(smtp);
        setIfMimeBody(ifMimeBody);
        return createMimeMessage()
                && setSubject(subject)
                && setBody(body)
                && setFrom(from)
                && setNamePass(senderUserName, senderPass)
                && setCopyTo(coypto)
                && setBlindCopyTo(bcto)
                && setTo(to)
                && addFileAffix(fileAffix)
                && sendout();

    }

    /**
     * 设置了服务器地址以及验证用户身份的信息
     *
     * @param subject
     * @param body
     * @param to
     * @param coypto
     * @param bcto
     * @param fileAffix
     * @return
     */
    private static boolean sendMail(String subject, String body,
                                    String to, String coypto,
                                    String bcto, String fileAffix) {
        String smtp = "smtp.qq.com";
        boolean ifMimeBody = true;

        // 发件邮箱和密码
        String senderUserName = "your mail address";
        String senderPassword = "password";
        String from = "your mail address";

        return sendMail(smtp, subject, body, ifMimeBody, from, to, coypto, bcto, senderUserName, senderPassword, fileAffix);
    }

    /**
     *
     * @param subject
     * @param body
     * @param to
     * @param fileAffix
     * @return
     */
    private static boolean sendMail(String subject, String body, String to, String fileAffix){
        return sendMail(subject, body, to, null, null, fileAffix);
    }


    //设定SMTP服务器。
    private static void setSmtpHost(String hostName) {
        if (props == null)
            props = System.getProperties(); //首先获得系统的Properties对象，然后设置SMTP和hostName
        props.put("mail.smtp.host", hostName);
    }


    //设定是否需要SMTP服务器验证
    private static void setNeedAuth(boolean need) {
        if (props == null)
            props = System.getProperties();
        if (need) {
            props.put("mail.smtp.auth", "true");
            props.put("mail.smtp.starttls.enable", "true");//使用 STARTTLS安全连接

        } else {
            props.put("mail.smtp.auth", "false");
        }
    }

    //设定用户和密码
    private static boolean setNamePass(String name, String pass) {
        username = name;
        password = pass;
        return true;
    }

    //新建邮件消息对象
    private static boolean createMimeMessage() {
        try {
            session = Session.getDefaultInstance(props, null);   //获取邮件会话
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        try {
            mimeMsg = new MimeMessage(session);     //用此session生成MimeMessage类型的邮件消息
            mp = new MimeMultipart();       //并生成MimeMultipart类型的消息内容
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    //设定邮件的标题
    private static boolean setSubject(String mailSubject) {
        try {
            mimeMsg.setSubject(mailSubject);
            return true;
        } catch (MessagingException e) {
            e.printStackTrace();
            System.out.println("设置邮件标题失败");
            return false;
        }
    }

    //设置是否MIME内容的标志位
    private static boolean isIfMimeBody() {
        return ifMimeBody;
    }

    private static void setIfMimeBody(boolean b) {
        ifMimeBody = b;
    }

    //设置邮件内容
    private static boolean setBody(String mailBody) {
        BodyPart bp = new MimeBodyPart();
        try {
            if (ifMimeBody) {
                bp.setContent("<meta http-equiv=Content-Type content=text/html;charset=utf-8"
                        + mailBody, "text/html;charset=utf-8");
            } else {
                bp.setText(mailBody);
            }
            mp.addBodyPart(bp);
            return true;
        } catch (MessagingException e) {
            e.printStackTrace();
            return false;
        }
    }


    //设置邮件附件
    private static boolean addFileAffix(String filename) {
        if (filename == null) {
            return true;
        }
        try {
            BodyPart bp = new MimeBodyPart();
            FileDataSource fileds = new FileDataSource(filename);
            bp.setDataHandler(new DataHandler(fileds));
            bp.setFileName(fileds.getName());
            mp.addBodyPart(bp);
            return true;
        } catch (MessagingException e) {
            e.printStackTrace();
            return false;
        }
    }

    //设置发送者
    private static boolean setFrom(String from) {
        try {
            mimeMsg.setFrom(new InternetAddress(from));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("发送者设置失败");
            return false;
        }
    }

    //设置接收者
    private static boolean setTo(String to) {
        if (to == null)
            return false;
        try {
            mimeMsg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("接收者设置失败");
            return false;
        }
    }

    private static boolean setCopyTo(String copyto) {
        if (copyto == null)
            return true;
        try {
            //注意这里addRecipients方法的第一个参数为Message.RecipientType.CC 指明这是一个抄送人
            mimeMsg.addRecipients(Message.RecipientType.CC, (Address[]) InternetAddress.parse(copyto));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    //设置暗抄送人
    private static boolean setBlindCopyTo(String copyto) {
        if (copyto == null)
            return true;
        try {
            //注意这里addRecipients方法的第一个参数为Message.RecipientType.CC 指明这是一个抄送人
            mimeMsg.addRecipients(Message.RecipientType.BCC, (Address[]) InternetAddress.parse(copyto));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    //发送
    private static boolean sendout() {
        try {
            //设置邮件内容 并保存
            mimeMsg.setContent(mp);
            mimeMsg.saveChanges();

            //从session 中生成Transport对象
            Session mailSession = Session.getInstance(props, null);
            Transport transport = mailSession.getTransport("smtp");

            //用 Transport 对象连接SMTP服务器
            transport.connect((String) props.get("mail.smtp.host"), username, password);

            //发送邮件 并退出
            transport.sendMessage(mimeMsg, mimeMsg.getAllRecipients());
            transport.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("sendout 失败");
            return false;
        }
    }

}
